﻿using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Bricks;
using Bricks.Injecting;

namespace Motar.ServiceModel
{
    
    /// <summary>
    /// 
    /// </summary>
    public class InjectingServiceBehavior : FacadeBase<IValueResolver<IInstanceProvider>>, IServiceBehavior
    {

        /// <summary>
        /// 
        /// </summary>
        public InjectingServiceBehavior() :
            this(new SingleValueResolver<IInstanceProvider, InjectingInstanceProvider>())
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        public InjectingServiceBehavior(string key) :
            this(new SingleValueResolver<IInstanceProvider, InjectingInstanceProvider>(key))
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="containerFacadeResolver"></param>
        public InjectingServiceBehavior(IValueResolver<IInstanceProvider> instanceProviderResolver) :
            base(() => instanceProviderResolver)
        {
            if (instanceProviderResolver == null)
            {
                throw new ArgumentNullException("instanceProviderResolver");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceDescription"></param>
        /// <param name="serviceHostBase"></param>
        /// <param name="endpoints"></param>
        /// <param name="bindingParameters"></param>
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceDescription"></param>
        /// <param name="serviceHostBase"></param>
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            Execute(instanceProviderResolver =>
            {
                foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
                {
                    foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
                    {
                        if (!endpointDispatcher.IsSystemEndpoint)
                        {
                            endpointDispatcher.DispatchRuntime.InstanceProvider = instanceProviderResolver.Resolve();
                        }
                    }
                }
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceDescription"></param>
        /// <param name="serviceHostBase"></param>
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
    }
}
